package com.jkoa.stripes.action;

import able.stripes.JSP;
import com.google.inject.Inject;
import com.jkoa.BaseActionBean;
import com.jkoa.model.Majikan;
import com.jkoa.model.Peribadi;
import com.jkoa.service.MajikanService;
import com.jkoa.service.ReportService;
import com.jkoa.stripes.config.AuthRequired;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ErrorResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.StreamingResolution;
import net.sourceforge.stripes.action.UrlBinding;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.displaytag.tags.TableTagParameters;
import org.displaytag.util.ParamEncoder;

/**

 * @author wan.fairul
 *
 */
@UrlBinding("/laporan")
@AuthRequired
public class LaporanActionBean extends BaseActionBean {

    private static final Logger logger = Logger.getLogger(LaporanActionBean.class);
    
    private List<Majikan> senaraiMajikan;
    
    private boolean flag = false;
    
    @Inject
    private MajikanService mservice;   
    

    @DefaultHandler
    public Resolution showForm() {
        return new JSP("laporan.jsp");
    }

    public Resolution search() {
        ParamEncoder encoder = new ParamEncoder("line");
        String page = getContext().getRequest().getParameter((encoder.encodeParameterName(TableTagParameters.PARAMETER_PAGE)));
        senaraiMajikan = mservice.findAll(getContext().getRequest().getParameterMap());
        setFlag(true);
        return new JSP("laporan.jsp");
    }
    
    public Resolution convertToPdf() {
        ReportService rpt = new ReportService();
        
        InputStream is = null;
        
        List<String> headers = getHeader(getContext().getRequest());
        List<String> values = new ArrayList<String>();
        Map<String,List> map = new HashMap<String,List>();
        List<String> valuesBilPekerja = new ArrayList<String>();
        List<String> valuesAlamatMajikan = new ArrayList<String>();
        List<String> valuesSenaraiPekerja = new ArrayList<String>();

        try {
            senaraiMajikan = mservice.findAll(getContext().getRequest().getParameterMap());
            for(String head : headers) {
                values = new ArrayList<String>();
                map = new HashMap<String,List>();
                if (head.equalsIgnoreCase("nama majikan")){
                    for(Majikan majikan : senaraiMajikan) {
                        values.add(majikan.getNamaMajikan());
                    }
                    map.put(head, values);
                } else if (head.equalsIgnoreCase("bil pekerja")) {
                    for(Majikan majikan : senaraiMajikan) {
                        values.add(majikan.getBilPekerja());
                    }
                    map.put(head, values);
                } else if (head.equalsIgnoreCase("alamat")) {
                    for(Majikan majikan : senaraiMajikan) {
                        values.add(majikan.getAlamatMajikan1());
                    }
                    map.put(head, values);
                }
            }            
            
            String path = rpt.cetakLaporan("laporan_majikan", senaraiMajikan);
            
            is = new FileInputStream(new File(path));
            
        } catch (Exception ex) {
            logger.error(ex);
            return new ErrorResolution(404);
        }

        return new StreamingResolution("application/pdf", is);
    }

    public Resolution convertToExcel() throws FileNotFoundException {
        
        String tmp = System.getProperty("java.io.tmpdir");
        File tmpdir = new File(tmp);
        File dir = new File(tmpdir, "generated_report_dir/");
        if (!dir.exists()) {
            dir.mkdir();
        }        
        String fileName = dir.getPath() +"tmp.xls";        
        List<String> headers = getHeader(getContext().getRequest());
        senaraiMajikan = mservice.findAll(getContext().getRequest().getParameterMap());
        writeDataToExcelFile(fileName, headers);
        FileInputStream fis = new FileInputStream(new File(fileName));
//        BufferedInputStream bis = new BufferedInputStream(fis);
        final BufferedInputStream bis = new BufferedInputStream(fis);
//        return new StreamingResolution("application/vnd.ms-excel", fis);
          return new StreamingResolution("application/vnd.ms-excel") {

                    @Override
                    public void stream(HttpServletResponse response) throws Exception {
                        response.setHeader("Cache-Control", "no-cache");
                        response.setHeader("Pragma", "no-cache");
                        response.setDateHeader("Expires", 0);
                        response.setHeader("Content-disposition", "inline; filename=laporan.xls");
//                        ImageToPdfConvertor image = new ImageToPdfConvertor();

//                        BufferedInputStream bis = new BufferedInputStream(
//                                new ByteArrayInputStream(image.imageToPdf(bufferedImages)));

                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                        int ch;
                        while ((ch = bis.read()) != -1) {
                            baos.write(ch);
                        }
                        baos.writeTo(response.getOutputStream());
                    }
                };
    }

    private void writeDataToExcelFile(String fileName, List<String> headers) {     
        String [][] excelData = preapreDataToWriteToExcel(headers, senaraiMajikan);
        HSSFWorkbook myWorkBook = new HSSFWorkbook();
        HSSFSheet mySheet = myWorkBook.createSheet();
        HSSFRow myRow = null;
        HSSFCell myCell = null;
        
        HSSFCellStyle cs = myWorkBook.createCellStyle();        
        cs.setFillForegroundColor(HSSFColor.GREY_25_PERCENT.index);
        cs.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        
        logger.info("len =" + excelData[0].length);
        

        for (int rowNum = 0; rowNum < senaraiMajikan.size()+1; rowNum++) {
            myRow = mySheet.createRow(rowNum);            
            myRow.setHeightInPoints(60);            

            for (int cellNum = 0; cellNum < excelData[0].length; cellNum++) {
                myCell = myRow.createCell(cellNum);                
                HSSFRichTextString str = new HSSFRichTextString(excelData[rowNum][cellNum]);
                myCell.setCellValue(str); 
                mySheet.autoSizeColumn((short)cellNum);       
//                myCell.setCellStyle(cs);
            }            
        }        

        try {
            FileOutputStream out = new FileOutputStream(fileName);
            myWorkBook.write(out);
            out.close();            
        } catch (Exception e) {
            logger.error(e);
        }
    }
    
    public String [][] preapreDataToWriteToExcel(List<String> headers, List<Majikan> datas){
         String [][] excelData = new String [10][10];
         
         //header            
         for (int i=0; i<headers.size(); i++) {
             String header = headers.get(i);
             excelData[0][i] = header;   
             int c = 1;
             int r = 0;
             logger.info("datas.size() = " + datas.size());
             for(int count = 0; count < datas.size(); count ++) {                 
                 if (c > (datas.size()+1) ) break;
                 logger.info("header = " + header);
                 logger.info("[" + c + "][" + i + "]");                 
                 Majikan majikan = datas.get(count);                                  
                 if (header.equalsIgnoreCase("nama majikan")) {
                      excelData[c][i] = majikan.getNamaMajikan();
                      logger.info("nama majikan = " + majikan.getNamaMajikan());
                 } else if (header.equalsIgnoreCase("bil pekerja")) {
                     excelData[c][i] = majikan.getBilPekerja();
                 } else if (header.equalsIgnoreCase("alamat")) {
                     excelData[c][i] = checkingStr(majikan.getAlamatMajikan1()) +
                             checkingStr(majikan.getAlamatMajikan2()) +
                             checkingStr(majikan.getAlamatMajikan3()) + 
                             checkingStr(majikan.getAlamatMajikan4()) + 
                             checkingStr(majikan.getAlamatPoskod()) + 
                             checkingStr(majikan.getAlamatNegeri().getNama());
                 } else if (header.equalsIgnoreCase("pekerja")) {
                     StringBuilder sb = new StringBuilder();
                     for (Peribadi pekerja : majikan.getSenaraiPekerja()){
                         sb.append("\n").append(pekerja.getNama());                                                  
                     }
                     excelData[c][i] = sb.toString();
                 } else {
                     excelData[c][i] = String.valueOf(c); 
                     logger.info(String.valueOf(c));
                 }                 
                 c = c+1;
             }             
         }
         return excelData;
    }
    
    private String checkingStr(String str) {
        return StringUtils.isNotBlank(str)? str +"," :"";
    }

    private List<String> getHeader(HttpServletRequest request) {
        List<String> headers = new ArrayList<String>();        
        headers.add("bil");
        for (Enumeration en = request.getParameterNames(); en.hasMoreElements();) {
            String name = (String) en.nextElement();
            if (!name.startsWith("header_")) {
                continue;
            }
            String param = name.replaceAll("header_", "");
            param = param.replaceAll("_", " ");
            String value = request.getParameter(name);
            logger.info("param : " + param + "= value :" + value);
            headers.add(param);
        }
        return headers;
    }

    public List<Majikan> getSenaraiMajikan() {
        return senaraiMajikan;
    }

    public void setSenaraiMajikan(List<Majikan> senaraiMajikan) {
        this.senaraiMajikan = senaraiMajikan;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}
